home assistant integration knowledge

安装量: 91
排名: #8827

安装

npx skills add https://github.com/home-assistant/core --skill 'Home Assistant Integration knowledge'
File Locations
Integration code
:
./homeassistant/components//
Integration tests
:
./tests/components//
Integration Templates
Standard Integration Structure
homeassistant/components/my_integration/
├── init.py # Entry point with async_setup_entry
├── manifest.json # Integration metadata and dependencies
├── const.py # Domain and constants
├── config_flow.py # UI configuration flow
├── coordinator.py # Data update coordinator (if needed)
├── entity.py # Base entity class (if shared patterns)
├── sensor.py # Sensor platform
├── strings.json # User-facing text and translations
├── services.yaml # Service definitions (if applicable)
└── quality_scale.yaml # Quality scale rule status
An integration can have platforms as needed (e.g.,
sensor.py
,
switch.py
, etc.). The following platforms have extra guidelines:
Diagnostics
:
platform-diagnostics.md
for diagnostic data collection
Repairs
:
platform-repairs.md
for user-actionable repair issues
Minimal Integration Checklist
manifest.json
with required fields (domain, name, codeowners, etc.)
init.py
with
async_setup_entry
and
async_unload_entry
config_flow.py
with UI configuration support
const.py
with
DOMAIN
constant
strings.json
with at least config flow text
Platform files (
sensor.py
, etc.) as needed
quality_scale.yaml
with rule status tracking
Integration Quality Scale
Home Assistant uses an Integration Quality Scale to ensure code quality and consistency. The quality level determines which rules apply:
Quality Scale Levels
Bronze
Basic requirements (ALL Bronze rules are mandatory)
Silver
Enhanced functionality
Gold
Advanced features
Platinum
Highest quality standards
Quality Scale Progression
Bronze → Silver
Add entity unavailability, parallel updates, auth flows
Silver → Gold
Add device management, diagnostics, translations
Gold → Platinum
Add strict typing, async dependencies, websession injection
How Rules Apply
Check
manifest.json
Look for
"quality_scale"
key to determine integration level
Bronze Rules
Always required for any integration with quality scale
Higher Tier Rules
Only apply if integration targets that tier or higher
Rule Status
Check
quality_scale.yaml
in integration folder for:
done
Rule implemented
exempt
Rule doesn't apply (with reason in comment)
todo
Rule needs implementation Example quality_scale.yaml Structure rules :

Bronze (mandatory)

config-flow : done entity-unique-id : done action-setup : status : exempt comment : Integration does not register custom actions.

Silver (if targeting Silver+)

entity-unavailable : done parallel-updates : done

Gold (if targeting Gold+)

devices : done diagnostics : done

Platinum (if targeting Platinum)

strict-typing
:
done
When Reviewing/Creating Code
Always check the integration's quality scale level and exemption status before applying rules.
Code Organization
Core Locations
Shared constants:
homeassistant/const.py
(use these instead of hardcoding)
Integration structure:
homeassistant/components/{domain}/const.py
- Constants
homeassistant/components/{domain}/models.py
- Data models
homeassistant/components/{domain}/coordinator.py
- Update coordinator
homeassistant/components/{domain}/config_flow.py
- Configuration flow
homeassistant/components/{domain}/{platform}.py
- Platform implementations
Common Modules
coordinator.py
Centralize data fetching logic class MyCoordinator ( DataUpdateCoordinator [ MyData ] ) : def init ( self , hass : HomeAssistant , client : MyClient , config_entry : ConfigEntry ) -

None : super ( ) . init ( hass , logger = LOGGER , name = DOMAIN , update_interval = timedelta ( minutes = 1 ) , config_entry = config_entry ,

✅ Pass config_entry - it's accepted and recommended

)
entity.py
Base entity definitions to reduce duplication
class
MyEntity
(
CoordinatorEntity
[
MyCoordinator
]
)
:
_attr_has_entity_name
=
True
Runtime Data Storage
Use ConfigEntry.runtime_data
Store non-persistent runtime data
type
MyIntegrationConfigEntry
=
ConfigEntry
[
MyClient
]
async
def
async_setup_entry
(
hass
:
HomeAssistant
,
entry
:
MyIntegrationConfigEntry
)
-
>
bool
:
client
=
MyClient
(
entry
.
data
[
CONF_HOST
]
)
entry
.
runtime_data
=
client
Manifest Requirements
Required Fields
:
domain
,
name
,
codeowners
,
integration_type
,
documentation
,
requirements
Integration Types
:
device
,
hub
,
service
,
system
,
helper
IoT Class
Always specify connectivity method (e.g.,
cloud_polling
,
local_polling
,
local_push
)
Discovery Methods
Add when applicable:
zeroconf
,
dhcp
,
bluetooth
,
ssdp
,
usb
Dependencies
Include platform dependencies (e.g.,
application_credentials
,
bluetooth_adapters
)
Config Flow Patterns
Version Control
Always set
VERSION = 1
and
MINOR_VERSION = 1
Unique ID Management
:
await
self
.
async_set_unique_id
(
device_unique_id
)
self
.
_abort_if_unique_id_configured
(
)
Error Handling
Define errors in
strings.json
under
config.error
Step Methods
Use standard naming (
async_step_user
,
async_step_discovery
, etc.)
Integration Ownership
manifest.json
Add GitHub usernames to
codeowners
:
{
"domain"
:
"my_integration"
,
"name"
:
"My Integration"
,
"codeowners"
:
[
"@me"
]
}
Async Dependencies (Platinum)
Requirement
All dependencies must use asyncio
Ensures efficient task handling without thread context switching
WebSession Injection (Platinum)
Pass WebSession
Support passing web sessions to dependencies
async
def
async_setup_entry
(
hass
:
HomeAssistant
,
entry
:
MyConfigEntry
)
-
>
bool
:
"""Set up integration from config entry."""
client
=
MyClient
(
entry
.
data
[
CONF_HOST
]
,
async_get_clientsession
(
hass
)
)
For cookies: Use
async_create_clientsession
(aiohttp) or
create_async_httpx_client
(httpx)
Data Update Coordinator
Standard Pattern
Use for efficient data management class MyCoordinator ( DataUpdateCoordinator ) : def init ( self , hass : HomeAssistant , client : MyClient , config_entry : ConfigEntry ) -

None : super ( ) . init ( hass , logger = LOGGER , name = DOMAIN , update_interval = timedelta ( minutes = 5 ) , config_entry = config_entry ,

✅ Pass config_entry - it's accepted and recommended

)
self
.
client
=
client
async
def
_async_update_data
(
self
)
:
try
:
return
await
self
.
client
.
fetch_data
(
)
except
ApiError
as
err
:
raise
UpdateFailed
(
f"API communication error:
{
err
}
"
)
Error Types
Use
UpdateFailed
for API errors,
ConfigEntryAuthFailed
for auth issues
Config Entry
Always pass
config_entry
parameter to coordinator - it's accepted and recommended
Integration Guidelines
Configuration Flow
UI Setup Required
All integrations must support configuration via UI
Manifest
Set
"config_flow": true
in
manifest.json
Data Storage
:
Connection-critical config: Store in
ConfigEntry.data
Non-critical settings: Store in
ConfigEntry.options
Validation
Always validate user input before creating entries
Config Entry Naming
:
❌ Do NOT allow users to set config entry names in config flows
Names are automatically generated or can be customized later in UI
✅ Exception: Helper integrations MAY allow custom names in config flow
Connection Testing
Test device/service connection during config flow:
try
:
await
client
.
get_data
(
)
except
MyException
:
errors
[
"base"
]
=
"cannot_connect"
Duplicate Prevention
Prevent duplicate configurations:

Using unique ID

await self . async_set_unique_id ( identifier ) self . _abort_if_unique_id_configured ( )

Using unique data

self
.
_async_abort_entries_match
(
{
CONF_HOST
:
user_input
[
CONF_HOST
]
}
)
Reauthentication Support
Required Method
Implement
async_step_reauth
in config flow
Credential Updates
Allow users to update credentials without re-adding
Validation
Verify account matches existing unique ID:
await
self
.
async_set_unique_id
(
user_id
)
self
.
_abort_if_unique_id_mismatch
(
reason
=
"wrong_account"
)
return
self
.
async_update_reload_and_abort
(
self
.
_get_reauth_entry
(
)
,
data_updates
=
{
CONF_API_TOKEN
:
user_input
[
CONF_API_TOKEN
]
}
)
Reconfiguration Flow
Purpose
Allow configuration updates without removing device
Implementation
Add
async_step_reconfigure
method
Validation
Prevent changing underlying account with
_abort_if_unique_id_mismatch
Device Discovery
Manifest Configuration
Add discovery method (zeroconf, dhcp, etc.)
{
"zeroconf"
:
[
"_mydevice._tcp.local."
]
}
Discovery Handler
Implement appropriate
async_step_*
method:
async
def
async_step_zeroconf
(
self
,
discovery_info
)
:
"""Handle zeroconf discovery."""
await
self
.
async_set_unique_id
(
discovery_info
.
properties
[
"serialno"
]
)
self
.
_abort_if_unique_id_configured
(
updates
=
{
CONF_HOST
:
discovery_info
.
host
}
)
Network Updates
Use discovery to update dynamic IP addresses
Network Discovery Implementation
Zeroconf/mDNS
Use async instances
aiozc
=
await
zeroconf
.
async_get_async_instance
(
hass
)
SSDP Discovery
Register callbacks with cleanup
entry
.
async_on_unload
(
ssdp
.
async_register_callback
(
hass
,
_async_discovered_device
,
{
"st"
:
"urn:schemas-upnp-org:device:ZonePlayer:1"
}
)
)
Bluetooth Integration
Manifest Dependencies
Add
bluetooth_adapters
to dependencies
Connectable
Set
"connectable": true
for connection-required devices
Scanner Usage
Always use shared scanner instance
scanner
=
bluetooth
.
async_get_scanner
(
)
entry
.
async_on_unload
(
bluetooth
.
async_register_callback
(
hass
,
_async_discovered_device
,
{
"service_uuid"
:
"example_uuid"
}
,
bluetooth
.
BluetoothScanningMode
.
ACTIVE
)
)
Connection Handling
Never reuse
BleakClient
instances, use 10+ second timeouts
Setup Validation
Test Before Setup
Verify integration can be set up in
async_setup_entry
Exception Handling
:
ConfigEntryNotReady
Device offline or temporary failure
ConfigEntryAuthFailed
Authentication issues
ConfigEntryError
Unresolvable setup problems
Config Entry Unloading
Required
Implement
async_unload_entry
for runtime removal/reload
Platform Unloading
Use
hass.config_entries.async_unload_platforms
Cleanup
Register callbacks with entry.async_on_unload : async def async_unload_entry ( hass : HomeAssistant , entry : MyConfigEntry ) -

bool : """Unload a config entry.""" if unload_ok := await hass . config_entries . async_unload_platforms ( entry , PLATFORMS ) : entry . runtime_data . listener ( )

Clean up resources

return
unload_ok
Service Actions
Registration
Register all service actions in
async_setup
, NOT in
async_setup_entry
Validation
Check config entry existence and loaded state:
async
def
async_setup
(
hass
:
HomeAssistant
,
config
:
ConfigType
)
-
>
bool
:
async
def
service_action
(
call
:
ServiceCall
)
-
>
ServiceResponse
:
if
not
(
entry
:=
hass
.
config_entries
.
async_get_entry
(
call
.
data
[
ATTR_CONFIG_ENTRY_ID
]
)
)
:
raise
ServiceValidationError
(
"Entry not found"
)
if
entry
.
state
is
not
ConfigEntryState
.
LOADED
:
raise
ServiceValidationError
(
"Entry not loaded"
)
Exception Handling
Raise appropriate exceptions:

For invalid input

if end_date < start_date : raise ServiceValidationError ( "End date must be after start date" )

For service errors

try
:
await
client
.
set_schedule
(
start_date
,
end_date
)
except
MyConnectionError
as
err
:
raise
HomeAssistantError
(
"Could not connect to the schedule"
)
from
err
Service Registration Patterns
Entity Services
Register on platform setup
platform
.
async_register_entity_service
(
"my_entity_service"
,
{
vol
.
Required
(
"parameter"
)
:
cv
.
string
}
,
"handle_service_method"
)
Service Schema
Always validate input
SERVICE_SCHEMA
=
vol
.
Schema
(
{
vol
.
Required
(
"entity_id"
)
:
cv
.
entity_ids
,
vol
.
Required
(
"parameter"
)
:
cv
.
string
,
vol
.
Optional
(
"timeout"
,
default
=
30
)
:
cv
.
positive_int
,
}
)
Services File
Create
services.yaml
with descriptions and field definitions
Polling
Use update coordinator pattern when possible
Polling intervals are NOT user-configurable
Never add scan_interval, update_interval, or polling frequency options to config flows or config entries
Integration determines intervals
Set
update_interval
programmatically based on integration logic, not user input
Minimum Intervals
:
Local network: 5 seconds
Cloud services: 60 seconds
Parallel Updates
Specify number of concurrent updates: PARALLEL_UPDATES = 1

Serialize updates to prevent overwhelming device

OR

PARALLEL_UPDATES

0

Unlimited (for coordinator-based or read-only)

Entity Development
Unique IDs
Required
Every entity must have a unique ID for registry tracking
Must be unique per platform (not per integration)
Don't include integration domain or platform in ID
Implementation
:
class
MySensor
(
SensorEntity
)
:
def
init
(
self
,
device_id
:
str
)
-
>
None
:
self
.
_attr_unique_id
=
f"
{
device_id
}
_temperature"
Acceptable ID Sources
:
Device serial numbers
MAC addresses (formatted using
format_mac
from device registry)
Physical identifiers (printed/EEPROM)
Config entry ID as last resort:
f"{entry.entry_id}-battery"
Never Use
:
IP addresses, hostnames, URLs
Device names
Email addresses, usernames
Entity Descriptions
Lambda/Anonymous Functions
Often used in EntityDescription for value transformation
Multiline Lambdas
When lambdas exceed line length, wrap in parentheses for readability Bad pattern : SensorEntityDescription ( key = "temperature" , name = "Temperature" , value_fn = lambda data : round ( data [ "temp_value" ] * 1.8 + 32 , 1 ) if data . get ( "temp_value" ) is not None else None ,

❌ Too long

) Good pattern : SensorEntityDescription ( key = "temperature" , name = "Temperature" , value_fn = lambda data : (

✅ Parenthesis on same line as lambda

round
(
data
[
"temp_value"
]
*
1.8
+
32
,
1
)
if
data
.
get
(
"temp_value"
)
is
not
None
else
None
)
,
)
Entity Naming
Use has_entity_name
Set _attr_has_entity_name = True For specific fields : class MySensor ( SensorEntity ) : _attr_has_entity_name = True def init ( self , device : Device , field : str ) -

None : self . _attr_device_info = DeviceInfo ( identifiers = { ( DOMAIN , device . id ) } , name = device . name , ) self . _attr_name = field

e.g., "temperature", "humidity"

For device itself
Set
_attr_name = None
Event Lifecycle Management
Subscribe in
async_added_to_hass
:
async
def
async_added_to_hass
(
self
)
-
>
None
:
"""Subscribe to events."""
self
.
async_on_remove
(
self
.
client
.
events
.
subscribe
(
"my_event"
,
self
.
_handle_event
)
)
Unsubscribe in
async_will_remove_from_hass
if not using
async_on_remove
Never subscribe in
init
or other methods
State Handling
Unknown values: Use
None
(not "unknown" or "unavailable")
Availability: Implement
available()
property instead of using "unavailable" state
Entity Availability
Mark Unavailable
When data cannot be fetched from device/service
Coordinator Pattern
:
@property
def
available
(
self
)
-
>
bool
:
"""Return if entity is available."""
return
super
(
)
.
available
and
self
.
identifier
in
self
.
coordinator
.
data
Direct Update Pattern
:
async
def
async_update
(
self
)
-
>
None
:
"""Update entity."""
try
:
data
=
await
self
.
client
.
get_data
(
)
except
MyException
:
self
.
_attr_available
=
False
else
:
self
.
_attr_available
=
True
self
.
_attr_native_value
=
data
.
value
Extra State Attributes
All attribute keys must always be present
Unknown values: Use
None
Provide descriptive attributes
Device Management
Device Registry
Create Devices
Group related entities under devices
Device Info
Provide comprehensive metadata:
_attr_device_info
=
DeviceInfo
(
connections
=
{
(
CONNECTION_NETWORK_MAC
,
device
.
mac
)
}
,
identifiers
=
{
(
DOMAIN
,
device
.
id
)
}
,
name
=
device
.
name
,
manufacturer
=
"My Company"
,
model
=
"My Sensor"
,
sw_version
=
device
.
version
,
)
For services: Add
entry_type=DeviceEntryType.SERVICE
Dynamic Device Addition
Auto-detect New Devices
After initial setup
Implementation Pattern
:
def
_check_device
(
)
-
>
None
:
current_devices
=
set
(
coordinator
.
data
)
new_devices
=
current_devices
-
known_devices
if
new_devices
:
known_devices
.
update
(
new_devices
)
async_add_entities
(
[
MySensor
(
coordinator
,
device_id
)
for
device_id
in
new_devices
]
)
entry
.
async_on_unload
(
coordinator
.
async_add_listener
(
_check_device
)
)
Stale Device Removal
Auto-remove
When devices disappear from hub/account
Device Registry Update
:
device_registry
.
async_update_device
(
device_id
=
device
.
id
,
remove_config_entry_id
=
self
.
config_entry
.
entry_id
,
)
Manual Deletion
Implement
async_remove_config_entry_device
when needed
Entity Categories
Required
Assign appropriate category to entities
Implementation
Set
_attr_entity_category
class
MySensor
(
SensorEntity
)
:
_attr_entity_category
=
EntityCategory
.
DIAGNOSTIC
Categories include:
DIAGNOSTIC
for system/technical information
Device Classes
Use When Available
Set appropriate device class for entity type
class
MyTemperatureSensor
(
SensorEntity
)
:
_attr_device_class
=
SensorDeviceClass
.
TEMPERATURE
Provides context for: unit conversion, voice control, UI representation
Disabled by Default
Disable Noisy/Less Popular Entities
Reduce resource usage
class
MySignalStrengthSensor
(
SensorEntity
)
:
_attr_entity_registry_enabled_default
=
False
Target: frequently changing states, technical diagnostics
Entity Translations
Required with has_entity_name
Support international users
Implementation
:
class
MySensor
(
SensorEntity
)
:
_attr_has_entity_name
=
True
_attr_translation_key
=
"phase_voltage"
Create
strings.json
with translations:
{
"entity"
:
{
"sensor"
:
{
"phase_voltage"
:
{
"name"
:
"Phase voltage"
}
}
}
}
Exception Translations (Gold)
Translatable Errors
Use translation keys for user-facing exceptions
Implementation
:
raise
ServiceValidationError
(
translation_domain
=
DOMAIN
,
translation_key
=
"end_date_before_start_date"
,
)
Add to
strings.json
:
{
"exceptions"
:
{
"end_date_before_start_date"
:
{
"message"
:
"The end date cannot be before the start date."
}
}
}
Icon Translations (Gold)
Dynamic Icons
Support state and range-based icon selection
State-based Icons
:
{
"entity"
:
{
"sensor"
:
{
"tree_pollen"
:
{
"default"
:
"mdi:tree"
,
"state"
:
{
"high"
:
"mdi:tree-outline"
}
}
}
}
}
Range-based Icons
(for numeric values):
{
"entity"
:
{
"sensor"
:
{
"battery_level"
:
{
"default"
:
"mdi:battery-unknown"
,
"range"
:
{
"0"
:
"mdi:battery-outline"
,
"90"
:
"mdi:battery-90"
,
"100"
:
"mdi:battery"
}
}
}
}
}
Testing Requirements
Location
:
tests/components/{domain}/
Coverage Requirement
Above 95% test coverage for all modules
Best Practices
:
Use pytest fixtures from
tests.common
Mock all external dependencies
Use snapshots for complex data structures
Follow existing test patterns
Config Flow Testing
100% Coverage Required
All config flow paths must be tested Test Scenarios : All flow initiation methods (user, discovery, import) Successful configuration paths Error recovery scenarios Prevention of duplicate entries Flow completion after errors Testing Integration-specific tests (recommended): pytest ./tests/components/ < integration_domain

\ --cov = homeassistant.components. < integration_domain

\ --cov-report term-missing \ --durations-min = 1 \ --durations = 0 \ --numprocesses = auto Testing Best Practices Never access hass.data directly - Use fixtures and proper integration setup instead Use snapshot testing - For verifying entity states and attributes Test through integration setup - Don't test entities in isolation Mock external APIs - Use fixtures with realistic JSON data Verify registries - Ensure entities are properly registered with devices Config Flow Testing Template async def test_user_flow_success ( hass , mock_api ) : """Test successful user flow.""" result = await hass . config_entries . flow . async_init ( DOMAIN , context = { "source" : config_entries . SOURCE_USER } ) assert result [ "type" ] == FlowResultType . FORM assert result [ "step_id" ] == "user"

Test form submission

result

await hass . config_entries . flow . async_configure ( result [ "flow_id" ] , user_input = TEST_USER_INPUT ) assert result [ "type" ] == FlowResultType . CREATE_ENTRY assert result [ "title" ] == "My Device" assert result [ "data" ] == TEST_USER_INPUT async def test_flow_connection_error ( hass , mock_api_error ) : """Test connection error handling.""" result = await hass . config_entries . flow . async_init ( DOMAIN , context = { "source" : config_entries . SOURCE_USER } ) result = await hass . config_entries . flow . async_configure ( result [ "flow_id" ] , user_input = TEST_USER_INPUT ) assert result [ "type" ] == FlowResultType . FORM assert result [ "errors" ] == { "base" : "cannot_connect" } Entity Testing Patterns @pytest . fixture def platforms ( ) -

list [ Platform ] : """Overridden fixture to specify platforms to test.""" return [ Platform . SENSOR ]

Or another specific platform as needed.

@pytest . mark . usefixtures ( "entity_registry_enabled_by_default" , "init_integration" ) async def test_entities ( hass : HomeAssistant , snapshot : SnapshotAssertion , entity_registry : er . EntityRegistry , device_registry : dr . DeviceRegistry , mock_config_entry : MockConfigEntry , ) -

None : """Test the sensor entities.""" await snapshot_platform ( hass , entity_registry , snapshot , mock_config_entry . entry_id )

Ensure entities are correctly assigned to device

device_entry

device_registry . async_get_device ( identifiers = { ( DOMAIN , "device_unique_id" ) } ) assert device_entry entity_entries = er . async_entries_for_config_entry ( entity_registry , mock_config_entry . entry_id ) for entity_entry in entity_entries : assert entity_entry . device_id == device_entry . id Mock Patterns

Modern integration fixture setup

@pytest
.
fixture
def
mock_config_entry
(
)
-
>
MockConfigEntry
:
"""Return the default mocked config entry."""
return
MockConfigEntry
(
title
=
"My Integration"
,
domain
=
DOMAIN
,
data
=
{
CONF_HOST
:
"127.0.0.1"
,
CONF_API_KEY
:
"test_key"
}
,
unique_id
=
"device_unique_id"
,
)
@pytest
.
fixture
def
mock_device_api
(
)
-
>
Generator
[
MagicMock
]
:
"""Return a mocked device API."""
with
patch
(
"homeassistant.components.my_integration.MyDeviceAPI"
,
autospec
=
True
)
as
api_mock
:
api
=
api_mock
.
return_value
api
.
get_data
.
return_value
=
MyDeviceData
.
from_json
(
load_fixture
(
"device_data.json"
,
DOMAIN
)
)
yield
api
@pytest
.
fixture
def
platforms
(
)
-
>
list
[
Platform
]
:
"""Fixture to specify platforms to test."""
return
PLATFORMS
@pytest
.
fixture
async
def
init_integration
(
hass
:
HomeAssistant
,
mock_config_entry
:
MockConfigEntry
,
mock_device_api
:
MagicMock
,
platforms
:
list
[
Platform
]
,
)
-
>
MockConfigEntry
:
"""Set up the integration for testing."""
mock_config_entry
.
add_to_hass
(
hass
)
with
patch
(
"homeassistant.components.my_integration.PLATFORMS"
,
platforms
)
:
await
hass
.
config_entries
.
async_setup
(
mock_config_entry
.
entry_id
)
await
hass
.
async_block_till_done
(
)
return
mock_config_entry
Debugging & Troubleshooting
Common Issues & Solutions
Integration won't load
Check
manifest.json
syntax and required fields
Entities not appearing
Verify
unique_id
and
has_entity_name
implementation
Config flow errors
Check
strings.json
entries and error handling
Discovery not working
Verify manifest discovery configuration and callbacks
Tests failing
Check mock setup and async context Debug Logging Setup

Enable debug logging in tests

caplog . set_level ( logging . DEBUG , logger = "my_integration" )

In integration code - use proper logging

_LOGGER

logging . getLogger ( name ) _LOGGER . debug ( "Processing data: %s" , data )

Use lazy logging

Validation Commands

Check specific integration

python -m script.hassfest --integration-path homeassistant/components/my_integration

Validate quality scale

Check quality_scale.yaml against current rules

Run integration tests with coverage

pytest ./tests/components/my_integration \ --cov = homeassistant.components.my_integration \ --cov-report term-missing

返回排行榜